# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: server\application.py
__author__ = "sanyi"
import logging, traceback
from werkzeug.wsgi import get_path_info
from server.http_responses.http_errors import HttpError, Http404, Http500

logger = logging.getLogger("server.application")


class Application:
    DEBUG_MODE = True

    def __init__(self, routers, error_handlers=None, watchdog_factory=None):
        self._Application__routers = routers
        self._Application__error_handlers = error_handlers if error_handlers else {}
        self._Application__errors_to_catch = tuple(
            self._Application__error_handlers.keys()
        )
        self._Application__watchdog_factory = watchdog_factory
        logger.info("server application initialized")

    def __call__(self, environment, start_response):
        path_info = get_path_info(environment)
        path = "/" + path_info.lstrip("/")
        scheme = environment["wsgi.url_scheme"].lower()
        host = environment["HTTP_HOST"].lower()
        method = environment.get("REQUEST_METHOD", "GET").lower()
        watchdog = None
        try:
            if self._Application__watchdog_factory:
                watchdog = self._Application__watchdog_factory()
                if watchdog:
                    watchdog.start()
            for router in self._Application__routers:
                try:
                    router.filter(scheme, host, method, path)
                except Http404:
                    pass

                logger.debug("handling %s:%s:%s", method, scheme, path)
                yield from router.handle_request(
                    method, scheme, path, environment, start_response
                )
                break
            else:
                raise Http404()

        except self._Application__errors_to_catch as e:
            for k in self._Application__errors_to_catch:
                if isinstance(e, k):
                    response = self._Application__error_handlers[e.__class__](e)
                    start_response(response.response_status, response.headers)
                    yield from response()
                    break
            else:
                logger.exception("unhandled server exception %s", e)
                response = Http500(message="Internal server exception")
                start_response(response.response_status, response.headers)
                yield from response()

        except HttpError as e:
            start_response(e.response_status, e.headers)
            yield from e()
        except Exception as e:
            logger.exception("unhandled server exception %s", e)
            if not self.DEBUG_MODE:
                response = Http500(message="Internal server exception")
            else:
                result = {
                    "exception": e.__class__.__name__,
                    "args": getattr(e, "args", None),
                    "extra": traceback.format_exc(),
                }
                response = Http500(
                    message="Internal Server Exception", details=[result]
                )
            start_response(response.response_status, response.headers)
            yield from response()
        finally:
            if watchdog:
                watchdog.cancel()
